www.gusucode.com > php框架系统:MDPHP麦迪源码 v1.xPHP源码程序 > php框架系统:MDPHP麦迪源码 v1.x/mdphp_v1.0.beta/mdphp_v1.0.beta/Library/Custom.php

    <?php

	/**
	 * 麦迪核心功能集
	 * @author: 麦迪科技 <i@md8.cc>
	 * @link: http://soft.md8.cc
	 * @version: 1.1
	 */

	namespace MDPHP;

	final class Custom{

		//执行时间记录变量
		static $workTime=array();

		/**
		 * 单入口初始化
		 */
		static public function start(){
			self::init();
			self::route();
			self::run();
		}

		static public function init(){

			//根目录
			if(!file_exists(MD_PATH)){
				mkdir(MD_PATH);
				file_put_contents(MD_PATH . 'index.html', '');
			}

			//公用文件
			if(!file_exists(MD_PATH . 'config.php'))
				copy(MD_ROOT.'Library/Default/config', MD_PATH.'config.php');
			if(!file_exists(MD_PATH . 'function.php'))
				file_put_contents(MD_PATH . 'function.php', '');

			//引入配置
			C(include MD_PATH.'config.php');

			$path = array(
				C('LAYER_V'),
				C('LAYER_A'),
				C('LAYER_C'),
				C('LAYER_R'),
				C('LAYER_P'),
				C('LAYER_A').'/'.ucwords(C('DEFAULT.CONTROLLER')),
				C('LAYER_V').'/'.ucwords(C('DEFAULT.CONTROLLER'))
			);

			foreach($path as $value){
				if(!file_exists(MD_PATH.$value.'/')){
					mkdir(MD_PATH.$value.'/') or error('无法初始化项目,请检查文件权限。');
					file_put_contents(MD_PATH.$value.'/index.html', '');
				}
			}

			//默认视图
			if(!file_get_contents($file=MD_PATH.end($path).'/'.C('DEFAULT.ACTION').C('TMPL_SUFFIX')))
				copy(MD_ROOT.'Library/Default/view', MD_PATH.C('LAYER_V').'/Index/index.html');

			//默认控制器
			if(!file_exists($file=MD_PATH.C('LAYER_C').'/'.C('DEFAULT.CONTROLLER').'.php'))
				copy(MD_ROOT.'Library/Default/controller', $file);

		}

		/**
		 * 路由
		 */
		static public function route(){

			//获取地址
			if(substr($_SERVER['REQUEST_URI'], 0, $n=strlen($_SERVER['SCRIPT_NAME'])) == $_SERVER['SCRIPT_NAME']){
				define('MD_BOOT_FILE', getFileName($_SERVER['SCRIPT_NAME']));
				$url = substr($_SERVER['REQUEST_URI'], $n);
			}elseif(substr($_SERVER['REQUEST_URI'], 0, $n=strlen(dirname($_SERVER['SCRIPT_NAME']))) == dirname($_SERVER['SCRIPT_NAME'])){
				$url = ltrim(substr($_SERVER['REQUEST_URI'], $n), '/');
			}else{
				$url = $_SERVER['PATH_INFO'];
			}
			define('MD_PATH_INFO', $url); $url=trim_left($url, '/');

		parse:{

			//获取模块、控制器、动作
			$url=parse_url($url);
			$array=(empty($url['path']) ? array() : explode('/', $url['path'])); $count=count($array); $default=C('DEFAULT');
			$defval=array($default['MODULE'], $default['CONTROLLER'], $default['ACTION']);
			for($i=0; $i<($count>3 ? 3 : $count); $i++){
				$array[$i] = (empty($array[$i]) ? $defval[$i] : $array[$i]);
			}
			switch($count){
				case 0:		#默认
					$m=$default['MODULE']; $c=$default['CONTROLLER']; $a=$default['ACTION'];
				break;
				case 1:		#方法
					$m=$default['MODULE']; $c=$default['CONTROLLER']; $a=$array[0];
					array_shift($array);
				break;
				case 2:		#控制器/方法
					$m=$default['MODULE']; $c=$array[0]; $a=$array[1];
					$array = array_splice($array, 2);
				break;
				default:	#模块/控制器/方法
					$m=$array[0]; $c=$array[1]; $a=$array[2];
					$array = array_splice($array, 3);
				break;
			}

			//智能模块检测
			if(in_array_case($c, array('_mdphp'))){											#系统
				$path=$c; $m=I('g.m', $default['MODULE'], 'ucwords');
			}else{
				if(file_exists(MD_PATH.
				(in_array_case($m, $default['MODULE']) && !file_exists(MD_PATH.ucwords($m).'/') ? '' : (ucwords($m).'/'))
				.C('LAYER_C').'/'.$c.'.php')){												#绝对

				}elseif(file_exists(MD_PATH.$c.'/')){										#简写
					$m=$c; $c=$default['CONTROLLER'];
				}
			}
			$modulePath = (in_array_case($m, $default['MODULE']) && !file_exists(MD_PATH.ucwords($m).'/') ? '' : (ucwords($m).'/'));

		}

			//检测路由规则
			if(!isset($config)){
				$config = array();
				$code = ($modulePath ? file_get_contents(MD_PATH.$modulePath.'config.php') : '') . file_get_contents(MD_PATH.'config.php');

				//路由规则状态
				preg_match('/[\'"]URL_ROUTER[\'"]\s*=>\s*(\S+)\s*(?:,|$)/', $code, $config[0]);
				$config[0] = str_replace('true', 1, strtolower(isset($config[0][1]) ? $config[0][1] : 0)) > 0;

				//路由规则开启
				if($config[0]){
					$url = MD_PATH_INFO;

					//路由规则列表
					preg_match('/[\'"]URL_ROUTE_RULES[\'"]\s*=>\s*array\s*\(([\s\S]+)\)\s*(?:,|$)/', $code, $config[1]);
					if(isset($config[1][1]))
						preg_match_all('/[\'"](.*?)[\'"]\s*=>\s*[\'"](.*?)[\'"]\s*(?:,|$)/', $config[1][1], $config[1]);
					else
						$config[1][1] = array();
				}
			}
			if(isset($config[0]) && $config[0]){
				for($i=0; $i<count($config[1][1]); $i++){
					if(($match=preg_replace($config[1][1][$i], $config[1][2][$i], $url)) != $url){
						if(($n=strpos($match, '?')) !== false){
							parse_str(substr($match, $n+1), $_GET);
							$url = substr($match, 0, $n);
							$config = true;
						}
					}
				}
				if($config===true) goto parse;
			}

			//检测模块是否存在
			if($modulePath && !file_exists(MD_PATH.$modulePath))
				error('Module_Not_Exist', MD_PATH.$modulePath);

			//更新模块信息
			if($modulePath){
				C(include MD_PATH . $modulePath . 'config.php');
				if(file_exists(MD_PATH.$modulePath.'function.php'))
					require MD_PATH.$modulePath.'function.php';
			}

			//设置常量
			define('MD_PATH_MODULE', $modulePath);													#模块目录

			############################### APP ###############################

			define('APP_PATH_COMPLETE', APP_PATH . MD_PATH_MODULE);									#完整目录
			define('APP_PATH_VIEW', APP_PATH_COMPLETE . C('LAYER_V') . '/');						#视图目录
			define('APP_PATH_CACHE', APP_PATH_COMPLETE . C('LAYER_R') . '/');						#缓存目录
			define('APP_PATH_COMMON', APP_PATH_COMPLETE . C('LAYER_A') . '/');						#公共目录
			define('APP_PATH_PLUGIN', APP_PATH_COMPLETE . C('LAYER_P') . '/');						#插件目录
			define('APP_PATH_CONTROLLER', APP_PATH_COMPLETE . C('LAYER_C') . '/');					#控制器目录

			############################## MDPHP ##############################

			define('MD_PATH_COMPLETE', MD_PATH . MD_PATH_MODULE);									#完整目录
			define('MD_PATH_VIEW', MD_ROOT . APP_PATH_VIEW);										#视图目录
			define('MD_PATH_CACHE', MD_ROOT . APP_PATH_CACHE);										#缓存目录
			define('MD_PATH_COMMON', MD_ROOT . APP_PATH_COMMON);									#公共目录
			define('MD_PATH_PLUGIN', MD_ROOT . APP_PATH_PLUGIN);									#插件目录
			define('MD_PATH_CONTROLLER', MD_ROOT . APP_PATH_CONTROLLER);							#控制器目录

			############################## SYSTEM ##############################

			self::$workTime['stop'] = microtime(true);
			define('EXECUTE_TIME', round(self::$workTime['stop']-self::$workTime['start'], 4));		#处理时间
			define('IS_GET', $_SERVER['REQUEST_METHOD'] == 'GET');									#GET请求
			define('IS_POST', $_SERVER['REQUEST_METHOD'] == 'POST');								#POST请求
			define('IS_PUT', $_SERVER['REQUEST_METHOD'] == 'PUT');									#PUT请求
			define('IS_DELETE', $_SERVER['REQUEST_METHOD'] == 'DELETE');							#DELETE请求
			define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
																									#AJAX请求
			define('MDPHP_CACHE', true);															#安全标志

			//后缀处理
			if(!defined('MD_SUFFIX') && ($ext=getFileExt($a))){
				define('MD_SUFFIX', $ext);															#伪静态后缀
				$a = substr($a, 0, -strlen(MD_SUFFIX)-1);
			}

			//参数处理
			for($i=0; $i<(count($array)/2); $i++){
				$_GET[@$array[$i*2]] = @$array[($i*2)+1];
			}

			//定义操作
			define('MD_MOD', ucwords($m));															#模块
			define('MD_CTR', $c);																	#控制器
			define('MD_ACT', $a);																	#动作

			//检测Action
			if(file_exists($actionPath=MD_PATH_CONTROLLER.MD_CTR.'Action.php'))
				require $actionPath;

			//引入代码
			if(isset($path)){
				define('MD_PREFIX_CTR', '');
				import('$->Library->Special->' . MD_CTR);
			}else{
				$path = MD_PATH_CONTROLLER . MD_CTR . '.php';
				if(file_exists($path))
					require $path;
				else
					error('Controller_Not_Exist', $path);
				define('MD_PREFIX_CTR', '_');
			}

		}

		/**
		 * 跑方法
		 */
		static public function run(){

			//实例化控制器
			$MDPHP = self::call(MD_PREFIX_CTR . MD_CTR);

			//检测伪静态后缀
			/*if(defined('MD_SUFFIX') && MD_SUFFIX != C('TMPL_SUFFIX')){
				$MDPHP -> jump(U(MD_CTR . '/' . MD_ACT));
			}*/

			//更新公共信息
			require MD_PATH . 'function.php';

			//设置全局领域
			$GLOBALS['MDPHP'] =& $MDPHP;

			//设置协议头
			//header('Cache-control: ' . C('HTTP_CACHE_CONTROL')); #页面缓存控制
			header('X-Powered-By:MDPHP');
			if(strtolower($charset=C('DOC_CHARSET')) != 'utf-8')
				header('Content-Type:text/html; charset=' . $charset);

			//开启SESSION
			C('SESSION.START') && session_start();

			//设置时区
			date_default_timezone_set(C('DEFAULT.TIMEZONE'));

			//方法检测
			if(!method_exists($MDPHP, MD_ACT)){
				if(method_exists($MDPHP, '__empty'))
					$MDPHP->__empty();
				else
					error('Action_Not_Exist', MD_ACT);
			}

			//非调试模式
			if(!constant('APP_DEBUG')){

				//获取缓存
				$Cache = new Cache;
				$data = $Cache->get(MD_CTR.MD_ACT);
				if(is_null($data)){

					//GZIP压缩
					$GZIP = C('COMPRESS.GZIP');

					//缓冲开始
					ob_start();

					//开始运行
					method_exists($MDPHP, '__init') && $MDPHP->__init();
					$MDPHP->{MD_ACT}();

					//缓冲结束
					$data = ob_get_clean();

					//GZIP处理
					$data = $GZIP ? ob_gzip($data) : $data;

					//添加缓存
					$Cache->add(MD_CTR.MD_ACT, $data);

				}

				echo $data;
				return;

			}

			//正常运行
			method_exists($MDPHP, '__init') && $MDPHP->__init();
			$MDPHP->{MD_ACT}();

			//DEBUG处理
			if(MD_PREFIX_CTR && constant('APP_DEBUG_TOOL')){
				$const = get_defined_constants(true);
				self::log(array(
					'CONST'		=>	array_map(function($v){
										return htmlspecialchars($v);
									}, $const['user']),
					'REQUEST'	=>	array('GET'=>I('G'), 'POST'=>I('P'), 'COOKIE'=>cookie()),
				), 'S');
				$debug = self::log();
				include MD_ROOT.'Library/Default/debug';
			}

		}

		/**
		 * 致命错误处理函数
		 */
		static public function fatalError(){
			if($info = error_get_last()){
				switch($info['type']){
					case E_ERROR:
					case E_PARSE:
					case E_CORE_ERROR:
					case E_COMPILE_ERROR:
					case E_USER_ERROR:
						ob_end_clean();
						halt(array(
							'title'		=>	'致命错误',
							'file'		=>	$info['file'],
							'line'		=>	$info['line'],
							'message'	=>	$info['message'],
						));
					break;
			    }
			}
		}

		/**
		 * 中级错误处理函数
		 * @param	integer	$errno		错误级别
		 * @param	string	$errstr		错误信息
		 * @param	string	$errfile	错误文件名
		 * @param	integer	$errline	错误行号
		 */
		static public function errorHandler($errno, $errstr, $errfile, $errline){
			switch($errno){
				case E_ERROR:
				case E_PARSE:
				case E_CORE_ERROR:
				case E_COMPILE_ERROR:
				case E_USER_ERROR:
					ob_end_clean();
					halt(array(
						'title'		=>	'中级错误',
						'file'		=>	$info['file'],
						'line'		=>	$info['line'],
						'message'	=>	$info['message'],
					));
				break;
				default:
					Custom::log(array('line'=>$errline, 'file'=>$errfile, 'mess'=>$errstr));
				break;
			}
		}

		static public function appException(){
			//代写
		}

		/**
		 * call调用
		 * @param	string	$name	call名
		 * @param	string	$type	类型
		 */
		static public function call($name, $type='class'){
			switch($type){
				case 'function':
					return $name();
				break;
				case 'class':
					return new $name;
				break;
			}
		}

		/**
		 * 日志记录
		 * @param	array	$info	数据
		 * @param	string	$type	日志类型
		 */
		static public function log($info=null, $type='E'){
			static $_debug = array();
			if(is_null($info))
				return $_debug;
			if(constant('APP_DEBUG')){
				$array = array(
					'S'	=>	'System',
					'T'	=>	'Tpl',
					'Q'	=>	'Query',
					'R'	=>	'Require',
					'C'	=>	'Cache',
					'E'	=>	'Error'
				);
				$type = $array[strtoupper($type)];
				if($type == 'System'){
					if(!isset($_debug[$type])) $_debug[$type]=array();
					$_debug[$type] = array_merge($_debug[$type], $info);
				}elseif($type == 'Cache'){
					isset($_debug['Cache']['write'])	|| $_debug['Cache']['write']=0;
					isset($_debug['Cache']['success'])	|| $_debug['Cache']['success']=0;
					isset($_debug['Cache']['failure'])	|| $_debug['Cache']['failure']=0;
					if($info==0)
						$_debug['Cache']['write']++;
					elseif($info==1)
						$_debug['Cache']['success']++;
					elseif($info==2)
						$_debug['Cache']['failure']++;
				}else{
					$_debug[$type][] = $info;
				}
			}
		}

		/**
		 * 获取标签属性值
		 * @param	string	$code	参数代码
		 * @return	array			参数组
		 */
		static public function getTagAttrs($code){
			$xml = '<tpl><tag '.$code.' /></tpl>';
			$xml = simplexml_load_string($xml);
			if(!$xml) error('Xml tag error.');
			$xml = (array)($xml->tag->attributes());
			$array = array_change_key_case($xml['@attributes']);
			return $array;
		}

		/**
		 * 设置默认值
		 * @param	array	$project	被设置对象
		 * @param	array	$value		对应值
		 */
		static public function setDefaultValue(&$project, $value){
			arrayCallBack($project, function($v, $k, $a){
				return empty($v) ? $a : $v;
			}, $value);
		}

		/**
		 * 模板解析
		 * @param	string	$code	HTML代码
		 * @return	string			解析后的PHP代码
		 */
		static public function parsing($code){

			//获取配置
			$dlmter['left']		= preg_quote(C('LEFT_DLMTER'));
			$dlmter['right']	= preg_quote(C('RIGHT_DLMTER'));

			//if
			$code = preg_replace_callback('/'.$dlmter['left'].' *if *([^{]+?) *'.$dlmter['right'].'/', function($m){
				$m[1] = preg_replace_callback('/(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.]*)/', function($s){
					return Custom::parseVar($s[1]);
				}, $m[1]);
				return '<?php if' . $m[1] . ': ?>';
			}, $code);
			$code = preg_replace('/'.$dlmter['left'].' *else *'.$dlmter['right'].'/', '<?php else: ?>', $code);
			$code = preg_replace_callback('/'.$dlmter['left'].' *elseif *([^{]+?) *'.$dlmter['right'].'/', function($m){
				$m[1] = preg_replace_callback('/(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.]*)/', function($s){
					return Custom::parseVar($s[1]);
				}, $m[1]);
				return '<?php elseif' . $m[1] . ': ?>';
			}, $code);
			$code = preg_replace ('/'.$dlmter['left'].' *\/if *'.$dlmter['right'].'/', '<?php endif; ?>', $code);

			//foreach
			$code = preg_replace_callback('/'.$dlmter['left'].' *foreach *([^{]+?) *'.$dlmter['right'].'/', function($m){
				$m[1] = preg_replace_callback('/(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.]*)/', function($s){
					return Custom::parseVar($s[1]);
				}, $m[1]);
				return '<?php foreach' . $m[1] . ': ?>';
			}, $code);
			$code = preg_replace('/'.$dlmter['left'].' *\/foreach *'.$dlmter['right'].'/', '<?php endforeach; ?>', $code);

			//for
			$code = preg_replace_callback('/'.$dlmter['left'].' *for *([^{]+?) *'.$dlmter['right'].'/', function($m){
				$m[1] = preg_replace_callback('/(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.]*)/', function($s){
					return Custom::parseVar($s[1]);
				}, $m[1]);
				return '<?php for' . $m[1] . ': ?>';
			}, $code);
			$code = preg_replace('/'.$dlmter['left'].' *\/for *'.$dlmter['right'].'/', '<?php endfor; ?>', $code);

			//变量
			$code = preg_replace_callback('/'.$dlmter['left'].' *([\+\-]*)(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.\+\-\/\*%]*) *'.$dlmter['right'].'/', function($m){
				return '<?php echo ' . $m[1] . Custom::parseVar($m[2]) . '; ?>';
			}, $code);

			//常量
			$code = preg_replace('/'.$dlmter['left'].' *([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*) *'.$dlmter['right'].'/', '<?php echo \\1; ?>', $code);

			//方法
			$code = preg_replace_callback('/'.$dlmter['left'].'@ *(.[\s\S]*?) *'.$dlmter['right'].'/s', function($m){
				$m[1] = preg_replace_callback('/(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\\\'\"\.]*)/', function($s){
					return Custom::parseVar($s[1]);
				}, $m[1]);
				return '<?php echo (' . $m[1] . '); ?>';
			}, $code);

			//特殊符号
			$code = str_replace(array('?><?php', "?>\r\n<?php", '__TMPL__'), array('', '', getRootPath().($tmpl=C('LAYER_T') ? $tmpl : (APP_PATH_VIEW.ucfirst(MD_CTR)))), $code);

			//压缩处理
			if(C('COMPRESS.HTML')){
				$code = compress_html($code);
			}

			return $code;

		}

		/**
		 * 删除数组中指定值对应的项
		 * @param	[type]		$value		任何值
		 * @param	array		&$array		欲处理的数组
		 * @param	boolean		$strict		是否检查类型相等
		 * @param	integer		$count		处理级别
		 * @return	array
		 */
		static public function delArrayByValue($value, &$array, $strict=false, $count=9999999){
			foreach($array as $k => $v){
				if(is_array($v)){
					if($count--){
						self::delArrayByValue($value, $v, $strict, $count);
						$array[$k] = $v;
						if(!count($v)) unset($array[$k]);
					}
				}else{
					if($strict){
						if($v === $value) unset($array[$k]);
					}else{
						if($v == $value) unset($array[$k]);
					}
				}
			}
		}

		/**
		 * 变量解析
		 * @param	string	$code	代码
		 * @return	[type]			返回变量数据
		 */
		static public function parseVar($code, $object=false){

			if(substr($code, 0, 1) == '$')
				$code = substr($code, 1);

			$arr=explode('[', $code); $key=0;
			while(++$key < count($arr)){
				while(($num=strpos($arr[$key], ']')) !== false){
					$str = substr($arr[$key], 0, $num);
					array_splice($arr, $key++, 0, $str);
					$arr[$key] = substr($arr[$key], $num+1);
					$arr[$key] = (substr($arr[$key], 0, 1)=='.' ? substr($arr[$key], 1) : $arr[$key]);
				}
			}
			self::delArrayByValue(false, $arr, true);
			$arr = explode('.', implode('.', $arr));

			if($object)
				$str = '$this->' . (strpos($arr[0], "'")===false ? $arr[0] : '{\'' . self::parseSingle($arr[0]) . '\'}');
			else
				$str = '$' . (strpos($arr[0], "'")===false ? $arr[0] : '{\'' . self::parseSingle($arr[0]) . '\'}');
			foreach($arr as $key=>$value){
				if($key != 0){
					if(in_array(substr($value, 0, 1), array("'", '"')) && in_array(substr($value, -1), array("'", '"')))
						$value = substr($value, 1, -1);
					$str .= '[' . (is_numeric($value) ? $value : "'" . self::parseSingle($value) . "'") . ']';
				}
			}
			return $str;

		}

		/**
		 * 单引号过滤
		 * @param	string	$str	数据
		 * @return	string/array			处理后数据
		 */
		static public function parseSingle($str){
			return addcslashes($str, "'");
		}

		/**
		 * 提交数据HTML代码转义
		 * @param	string/array	$data	数据
		 * @return	string/array			处理后数据
		 */
		static public function runMagicQuotes($data, $filter){
			if(is_array($data)){
				foreach($data as $key => $value){
					$data[$key] = self::runMagicQuotes($value, $filter);
				}
			}else{
				$data = call_user_func($filter, $data);
			}
			return $data;
		}

		/**
		 * 解析原生Cookie信息
		 * @param	string	$cookie	Cookie文本, 为空使用当前网页Cookie
		 * @return	array			Cookie组
		 */
		static public function parseCookie($cookie=null){
			if($cookie === null) $cookie = $_SERVER['HTTP_COOKIE'];
			$array = array(); $cookie = explode(';', $cookie);
			foreach($cookie as $key=>$value){
				$value = trim($value);
				if($value){
					$a = explode('=', $value);
					$array[$a[0]] = isset($a[1]) ? $a[1] : '';
				}
			}
			return $array;
		}

	}